home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Libraries / grayimage / endian_io.h < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-30  |  4.4 KB  |  170 lines  |  [TEXT/R*ch]

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *               Class Endian_IO
  6.  *    to read integers of various sizes taking the byte order
  7.  *                into account
  8.  *              and bit-stream IO
  9.  *
  10.  *   Two different byte orders are supported
  11.  *    bigendian    - most significant byte first
  12.  *    littleendian    - most significant byte last
  13.  *
  14.  ************************************************************************
  15.  */
  16.  
  17. //#pragma once
  18. #ifndef endian_io_h
  19. #define endian_io_h
  20.  
  21. #pragma interface
  22.  
  23. #include <fstream.h>
  24. #include "myenv.h"
  25.  
  26.  
  27. class EndianIO : public fstream {
  28.  
  29. private:
  30.   enum { MSBfirst, LSBfirst } byte_order;
  31.   enum { attached = 0x40000000 };    // Mask for ios::_flags, meaning the
  32.                     // stream is attached and the buffer
  33.                     // should not be closed/destroyed
  34. public:
  35.   EndianIO() : fstream() { byte_order = LSBfirst; }
  36.   EndianIO(EndianIO& file);        // Open by example. File handle of
  37.                     // 'file' is dup-ed, so closing the
  38.                     // present file would not close 'file'
  39.   EndianIO(const char * file_name, const int mode) : 
  40.           fstream(file_name,mode) { byte_order = LSBfirst; }
  41.   ~EndianIO();
  42.  
  43.                 // Deferred opening by example
  44.   EndianIO& open(EndianIO& a_file);
  45.  
  46.   void open(const char * file_name, const int mode) 
  47.     { fstream::open(file_name,mode); }
  48.  
  49.   void close(void);        // Close the stream
  50.  
  51.   void set_bigendian(void)          // Most significant byte first
  52.                   { byte_order = MSBfirst; }
  53.   void set_littlendian(void)        // Least significant byte first
  54.                 { byte_order = LSBfirst; }
  55.  
  56.                 // Returns TRUE if something goes wrong
  57.                 // with the I/O
  58.   int operator ! ()    { return !good(); }
  59.   void error(const char *descr);
  60.  
  61.   int readable(void) const { return !(rdbuf()->_flags & _IO_NO_READS); }
  62.   int writable(void) const { return !(rdbuf()->_flags & _IO_NO_WRITES); }
  63.  
  64.                 // The following I/O functions take
  65.                 // the char string op_description
  66.                 // that tells what this operation is for
  67.                 // On error, this string is printed along
  68.                 // with the error description
  69.   unsigned char  read_byte(const char * op_description);
  70.   unsigned short read_short(const char * op_description);
  71.   unsigned long  read_long(const char * op_description);
  72.  
  73.                 // Note, the first operand of write_byte
  74.                 // has to be specified as 'int' rather
  75.                 // than 'unsigned char', as bizarre as
  76.                 // it may seem. Otherwise, write_byte(0xff)
  77.                 // results in the i/o error
  78.                 // 'Inappropriate IOCTL for device'
  79.                 // after some 2000-4000 writings such a byte.
  80.   void write_byte(const int item, const char * op_description = "");
  81.   void write_short(const unsigned short item, const char* op_description = "");
  82.   void write_long(const unsigned long item, const char * op_description = "");
  83. };
  84.  
  85. inline unsigned char EndianIO::read_byte(const char * op_description) 
  86. {
  87.   unsigned char c;
  88.   if( !get(c) )
  89.     error(op_description);
  90.   return c;
  91. }
  92.  
  93. /*
  94.  *------------------------------------------------------------------------
  95.  *            Bit-stream Input-Output
  96.  */
  97.  
  98. class BitIO : public EndianIO
  99. {
  100. private:
  101.   unsigned char buffer;
  102.   const short buffer_capacity = 8;
  103.   short bits_in_buffer;
  104.  
  105. public:
  106.             // This is a dummy constructor. Use open() function
  107.             // of EndianIO class to perform the actual opening
  108.   BitIO() : EndianIO()            { bits_in_buffer = 0; }
  109.   ~BitIO();
  110.  
  111.   void put_bit(const char bit);        // Write a bit into the output stream
  112.   int  get_bit(void);            // Get a bit from the input stream
  113.   void close(void);            // Close the stream
  114. };
  115.  
  116.             // Put a bit (0/1) into the bit stream
  117. inline void BitIO::put_bit(const char bit)
  118. {
  119.   if( bit )
  120.     buffer = (buffer << 1) | 1;
  121.   else
  122.     buffer <<= 1;
  123.   if( ++bits_in_buffer == buffer_capacity )
  124.     write_byte(buffer), bits_in_buffer = 0;
  125. }
  126.  
  127.             // Close the stream on destructing it
  128. inline BitIO::~BitIO()
  129. {
  130.   close();
  131. }
  132.             // Flush the bit buffer on closing the stream      
  133. inline void BitIO::close(void)
  134. {
  135.                     // If the buffer contains something
  136.   if( writable() && bits_in_buffer > 0 )
  137.   {
  138.     buffer <<= buffer_capacity - bits_in_buffer; // Fill the rest with zeros
  139.     write_byte(buffer);            // Flush the buffer
  140.     bits_in_buffer = 0;
  141.   }
  142.   EndianIO::close();
  143. }
  144.  
  145.  
  146.             // Read a bit from the bit stream
  147. inline int BitIO::get_bit(void)
  148. {
  149.   if( bits_in_buffer == 0 )
  150.   {
  151.     if( eof() ) 
  152.       error("Reading an 8-bit chunk");
  153.     get(buffer);
  154.     bits_in_buffer = buffer_capacity;
  155.   }
  156.   bits_in_buffer--;
  157.   if( buffer & 0x80 )
  158.   {
  159.     buffer <<= 1;
  160.     return 1;
  161.   }
  162.   else
  163.   {
  164.     buffer <<= 1;
  165.     return 0;
  166.   }
  167. }
  168.  
  169. #endif
  170.